home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15 / Base / Exceptions.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-19  |  9.8 KB  |  356 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        Exceptions.h
  3.  
  4.     Contains:    exception handling macros
  5.  
  6.     Written by:    Bruce Horn, Steve Capps, Larry Kenyon, John Meier, scott douglass, Darin Adler,
  7.                 Paul Mercer, Bryan Stearns, Dave Owens
  8.                 
  9.                 Andy Nicholas
  10.  
  11.     Copyright:    © 1988-1995 by Apple Computer, Inc., all rights reserved.
  12.  
  13.          <2>     2/24/95    ga        
  14. */
  15.  
  16. #ifndef Exceptions_h
  17. #define Exceptions_h
  18.  
  19. typedef SInt32 ExceptionCode;
  20.  
  21. #define gExceptionStack        __except_buffer
  22. #define Throw(err)            throw (ExceptionCode)(err)
  23. #define Try                    try
  24. #define Catch(err)            catch(ExceptionCode err)
  25.  
  26.  
  27. #define eUnimplemented        -29999
  28. #define eWrongDataType        -30000
  29. #define eRequireFailed        -30001
  30. #define eIndexOutOfRange    -30002
  31. #define eDataCorrupt        -30003
  32. #define eLinksCorrupt        -30004
  33. #define eNilPtr                'nilP'
  34.  
  35. #define Require(x)        if(x == false) Throw(eRequireFailed);
  36.  
  37. #define FailNil(x)        if(x == nil) Throw(eNilPtr)
  38.  
  39. #define NOREGISTER(x)    (&x)
  40.  
  41. //----------------------------------------------------------------------------------------
  42. // FailErr: 
  43. //----------------------------------------------------------------------------------------
  44. inline void FailErr(ExceptionCode error)
  45.     {
  46.     if (error != 0)
  47.         Throw(error);
  48.     }
  49.  
  50. class TException;
  51.  
  52. extern TException*     gExceptionStack;
  53.  
  54. #if 0
  55.  
  56. #include <Types.h>
  57. #include <setjmp.h>
  58.  
  59. #ifdef METROWERKSPOWERPC
  60. struct DestructorChain;            // Forward declaration of Metrowerks local destructor chain type
  61. #endif
  62.  
  63. extern SInt32            gExceptionMessage;
  64. extern SInt32            gExceptionError;
  65.  
  66. void    Fail(SInt32, SInt32 message);
  67. void    FailErr(SInt32);
  68. void    FailAgain();
  69. void    FailNil(void*);
  70.  
  71. const long nilPtrErr = -110;    // Same as memAdrErr--odd or out of range
  72. const OSErr ePointerNil                = -110;
  73. const OSErr eGeneralErr                = -1;
  74. const OSErr eAssertionFailure        = -30000;
  75. const OSErr eRequirementNotMet        = -30001;
  76. const OSErr eValueOutOfRange        = -30002;
  77. const OSErr eIndexOutOfRange        = -30003;
  78. const OSErr eLinksCorrupt            = -30004;
  79. const OSErr eDataCorrupt            = -30005;
  80. const OSErr eWrongDataType            = -30006;
  81. const OSErr eFunctionNotHandledByClass = -30007;
  82.  
  83. //----------------------------------------------------------------------------------------
  84. // Except_Error: 
  85. //----------------------------------------------------------------------------------------
  86. inline SInt32    Except_Error()
  87.         { 
  88.         return gExceptionError; 
  89.         }
  90.  
  91. //----------------------------------------------------------------------------------------
  92. // Except_Message: 
  93. //----------------------------------------------------------------------------------------
  94. inline SInt32    Except_Message()
  95.         {
  96.         return gExceptionMessage; 
  97.         }
  98.  
  99. //----------------------------------------------------------------------------------------
  100. // ExpectError: 
  101. //----------------------------------------------------------------------------------------
  102. inline void ExpectError(OSErr error)
  103.         { 
  104.         if (Except_Error() != error) FailAgain(); 
  105.         }
  106.  
  107. //----------------------------------------------------------------------------------------
  108. // FailErr: 
  109. //----------------------------------------------------------------------------------------
  110. inline void FailErr(SInt32 error)
  111.     {
  112.     if (error != noErr)
  113.         Fail(error, 0);
  114.     }
  115.  
  116. //----------------------------------------------------------------------------------------
  117. // FailNil: 
  118. //----------------------------------------------------------------------------------------
  119. inline void FailNil(void *pointer)
  120.     {
  121.     if (pointer == nil)
  122.         FailErr(nilPtrErr);
  123.     }
  124.  
  125. //========================================================================================
  126. // CLASS TExceptionAction
  127. //
  128. // Exception action objects may be attached to the current exception handler; if
  129. // an exception is thrown, then the virtual method 'CatchException' is called, and
  130. // the exception-action object may do whatever cleanup it needs to.
  131. //========================================================================================
  132.  
  133. class TExceptionAction
  134.     {
  135. public:
  136.     virtual void        CatchException() = 0;
  137.     
  138.     TExceptionAction*    GetNextExceptionAction() { return fNextAction; }
  139.     void                SetNextExceptionAction(TExceptionAction* nextAction) { fNextAction = nextAction; }
  140.  
  141. private:
  142.     TExceptionAction*    fNextAction;
  143.     };
  144.     
  145.         
  146. //========================================================================================
  147. // CLASS TException
  148. //========================================================================================
  149.  
  150. class TException
  151.     {
  152. public:
  153.     
  154.     //
  155.     // --- Methods -------------------------------------------------------------------------------------
  156.     //
  157.                         TException();                // to set up next & fired
  158.                          ~TException();                // to remove from the exceptions stack
  159.  
  160.     void                AddExceptionAction(TExceptionAction* exceptAction);                // Add an exception action object to the the exception frame
  161.     TExceptionAction*    RemoveExceptionAction(TExceptionAction* exceptAction = nil);    // Remove a loop from the exception frame 
  162.     
  163.     //
  164.     // --- Fields --------------------------------------------------------------------------------------
  165.     //
  166.     jmp_buf                fEnv;                    // jmp_buf has to be first
  167.     
  168. #ifdef SIXTYEIGHTK
  169.     SInt32                fA5;                    // Save the current A5
  170. #endif
  171.  
  172. #ifdef METROWERKSPOWERPC
  173.     DestructorChain*     fLocalDestructorChain;    // • temporary Metrowerks hack
  174. #endif
  175.  
  176.     TExceptionAction*    fExceptionAction;        // A pointer to the first exception action object
  177.     TException*            fPrevious;                // A pointer to the previous exception frame on the stack
  178.     
  179.     Boolean                fFired;    
  180.     };
  181.  
  182.  
  183. //----------------------------------------------------------------------------------------
  184. // TException::AddExceptionAction:
  185. //
  186. // Insert 'exceptAction' into the linked-list of exception-actions hanging off the
  187. // exception frame
  188. //----------------------------------------------------------------------------------------
  189. inline void TException::AddExceptionAction(TExceptionAction* exceptAction)
  190.     {
  191.     exceptAction->SetNextExceptionAction(fExceptionAction);
  192.     fExceptionAction = exceptAction;
  193.     }
  194.  
  195. //----------------------------------------------------------------------------------------
  196. // TException::RemoveExceptionAction:
  197. //
  198. // Remove a single loop from the linked-list of loops hanging off the exception frame
  199. //----------------------------------------------------------------------------------------
  200. inline TExceptionAction* TException::RemoveExceptionAction(TExceptionAction* exceptAction /* = nil */)
  201.     {
  202.     if((exceptAction == fExceptionAction) || (exceptAction == nil))
  203.         {
  204.         exceptAction = fExceptionAction;
  205.         fExceptionAction = fExceptionAction->GetNextExceptionAction();
  206.         }
  207.     else
  208.         {
  209.         TExceptionAction* actionList;
  210.         
  211.         while(actionList != nil)
  212.             {
  213.             TExceptionAction* nextAction = actionList->GetNextExceptionAction();
  214.             if(nextAction == exceptAction)
  215.                 {
  216.                 actionList->SetNextExceptionAction(nextAction->GetNextExceptionAction());
  217.                 actionList = nil;
  218.                 }
  219.             else
  220.                 actionList = nextAction;
  221.             }
  222.         }
  223.     
  224.     return exceptAction;
  225.     }
  226.  
  227.  
  228. //
  229. // TRY/EXCEPT/ENDTRY Usage:
  230. //
  231. // Advantage:        Every failure handler has its own scope
  232. // Disadvantage:    Requires ugly "ENDTRY", and forgetting it
  233. //                    causes strange errors much later in the file
  234. //
  235. //        TRY
  236. //            {
  237. //            // do something
  238. //            FailErr(SomeFnReturningOSErr());
  239. //            }
  240. //        EXCEPT
  241. //            {
  242. //            OSErr err = Except_Error();
  243. //
  244. //            // clean up
  245. //            FailAgain();
  246. //            }
  247. //        ENDTRY
  248. //
  249. #define TRY { TException exceptions_data; \
  250.             if (setjmp(exceptions_data.fEnv) == 0) {
  251. #define EXCEPT } else {
  252. #define ENDTRY } }
  253. #define NOREGISTER(x)    ((void)&x)
  254.  
  255. //
  256. // Try/Catch/Throw Usage:
  257. //
  258. // Advantage:        No ugly "ENDTRY"; looks very similar to C++ try/catch
  259. // Disadvantage:    Must wrap each failure handler in its own scope,
  260. //                    or you will get an error "fi defined twice"
  261. //
  262. //        OSErr err = noErr;
  263. //
  264. //        Try
  265. //            {
  266. //            // do something
  267. //            FailErr(SomeFnReturningOSErr());    // "Throw" is unconditional
  268. //            }
  269. //        Catch(err)
  270. //            {
  271. //            // clean up
  272. //            Throw(err);
  273. //            }
  274. //
  275. #define Try            TException fi; if(setjmp(fi.fEnv) == 0) for(; gExceptionStack == &fi; gExceptionStack = fi.fPrevious, fi.fFired = true)
  276. #define Catch(err)    else if((err = (OSErr) Except_Error()) != noErr)
  277. #define Throw(err)    Fail(err, 0)
  278. #define Require(b)    if(b == false) Throw(-1)
  279.  
  280. //
  281. // try/catch/throw usage:
  282. //
  283. // Advantage:        Supported by the compiler, so it's portable
  284. // Disadvantage:    Most of our compilers don't provide exception handling
  285. //
  286. //        try
  287. //            {
  288. //            // do something
  289. //            FailErr(SomeFnReturningOSErr());    // "throw" is unconditional, so we still need a FailErr
  290. //            }
  291. //        catch(OSErr err)
  292. //            {
  293. //            // clean up
  294. //            throw(err);
  295. //            }
  296. //
  297.  
  298. //
  299. // How to combine Try/Catch with try/catch to form an 
  300. // exception mechanism that works on compilers that
  301. // do support exception handling, and also build on
  302. // compilers that do not support it:
  303. //
  304. // Define a type "ExceptionOSErr", which is just an
  305. // OSErr.   If exceptions are supported, ExceptionOSErr
  306. // is #defined to be OSErr.  If it is not supported,
  307. // then it is #defined to be nothing.
  308. //
  309. // The catch is that you must always use the type
  310. // ExceptionOSErr in your catch blocks, you must
  311. // always throw OSErrs, and the variable in the
  312. // catch block must always be exceptionErr.
  313. //
  314. //        try
  315. //            {
  316. //            // do something
  317. //            FailErr(SomeFnReturningOSErr());    // "throw" is unconditional, so we still need a FailErr
  318. //            }
  319. //        catch(ExceptionOSErr exceptionErr)
  320. //            {
  321. //            // clean up
  322. //            throw(err);
  323. //            }
  324. //
  325. // The problem is that our exception handler saves extra state
  326. // (TopMapHandle, CurMap, CurApRefNum, and Zone) that will NOT
  327. // be saved by a compiler-supported exception handler.
  328. //
  329. // I need to look into ways of patching into the 'try/catch'
  330. // process...
  331. //                - ga
  332. // 
  333. // EXCEPTIONSSUPPORTED
  334. //
  335.  
  336. #ifdef FUTURECODE // Don't use this yet...
  337.  
  338. // EXCEPTIONSSUPPORTED
  339.  
  340. #define ExceptionOSErr OSErr
  341.  
  342. // !EXCEPTIONSSUPPORTED
  343.  
  344. #define ExceptionOSErr OSErr
  345.  
  346. #define try            OSErr exceptionErr; TException fi; if(setjmp(fi.fEnv) == 0) while(fi.fFired == false)
  347. #define catch        else if((err = Except_Error()) != noErr)
  348. #define throw(err)    Fail(err, 0)
  349.  
  350. #endif // Don't use this yet
  351.  
  352. #endif
  353.  
  354. #endif
  355.  
  356.